#include "include/timer_wheel.h"
#include "include/thread_Pool.h"
#include <iostream>

static int64_t global_tick_ms_ = 0;
//=========================================================
// 构造 & 析构
//=========================================================
HAL::TimerWheel::TimerWheel(int tick_ms)
{
    this->_interval_ms = tick_ms;
    this->wheel_ms_.resize(1000/tick_ms);
    this->wheel_sec_.resize(60);
    this->wheel_min_.resize(60);
}

HAL::TimerWheel::~TimerWheel() {
    Stop();
}

//=========================================================
// 添加任务
//=========================================================
bool HAL::TimerWheel::AddTask(int delay_ms, TimerEvent &ev){
    if (delay_ms <= 0) {
        return false;
    }
    std::lock_guard<std::mutex> lock(_mutex_working);
    AddTaskNoLock(delay_ms, ev);
    return true;
}   
void HAL::TimerWheel::AddTaskNoLock(int delay_ms, TimerEvent &ev) {
    // 根据当前 cursor 计算新位置
    ev.pos = CalcPosition(delay_ms);
    // 记录执行周期
    ev.interval_ms = delay_ms;
    
    task_map_[ev.id] = nullptr;   // 占位

    if (ev.pos.min > 0) {
        wheel_min_[ev.pos.min].push_back(ev);
        task_map_[ev.id] = &wheel_min_[ev.pos.min].back();
        std::cout << "任务 " << ev.name << " 添加到分钟轮 " << ev.pos.min << std::endl;
    }
    else if (ev.pos.sec > 0) {
        wheel_sec_[ev.pos.sec].push_back(ev);
        task_map_[ev.id] = &wheel_sec_[ev.pos.sec].back();
        std::cout << "任务 " << ev.name << " 添加到秒轮 " << ev.pos.sec << std::endl;
    }
    else {
        wheel_ms_[ev.pos.ms].push_back(ev);
        task_map_[ev.id] = &wheel_ms_[ev.pos.ms].back();
        std::cout << "任务 " << ev.name << " 添加到毫秒轮 " << ev.pos.ms << std::endl;
    }
}

//=========================================================
// 取消任务
//=========================================================
void HAL::TimerWheel::CancelTask(int id) {
    std::lock_guard<std::mutex> lock(_mutex_working);

    auto it = task_map_.find(id);
    if (it != task_map_.end() && it->second != nullptr) {
        it->second->cancelled = true;
    }
}

//=========================================================
// 启动 & 停止
//=========================================================
void HAL::TimerWheel::Start() {
    if (_running) {
        return;
    }
    _running = true;
    _thread_working = std::thread(&TimerWheel::ThreadFunc, this);
}

void HAL::TimerWheel::Stop() {
    _running = false;
    std::cout << "准备停止定时器" << std::endl;
    if (_thread_working.joinable()) {
        _thread_working.join();
    }
    std::cout << "定时器已停止" << std::endl;
}

//=========================================================
// 时间轮线程
//=========================================================
void HAL::TimerWheel::ThreadFunc() {
    while (_running) {
        std::this_thread::sleep_for(std::chrono::milliseconds(_interval_ms));
        global_tick_ms_ += _interval_ms;
        Tick();
    }
}

//=========================================================
// 核心 tick
//=========================================================
void HAL::TimerWheel::Tick() {
    
    std::lock_guard<std::mutex> lock(_mutex_working);

    cursor_ms_++;
    if (cursor_ms_ >= wheel_ms_.size()) {
        cursor_ms_ = 0;
        TickSecondWheel();
    }
    //std::cout << "毫秒轮 tick " << cursor_ms_ << std::endl;

    auto& tasks = wheel_ms_[cursor_ms_];

    for (auto &task : tasks) {
        if (!task.cancelled) {
            //std::cout << "任务 " << task.id << " 执行" << std::endl;
            // 提交任务到线程池
            ThreadPool::getInstance().enqueue(task.callback);
        }
        
        if (task.repeat) {
            //std::cout << "任务 " << task.id << " 重复添加到毫秒轮 " << task.interval_ms << std::endl;
            //AddTaskNoLock((task.interval_ms), task);
            auto next_pos = cursor_ms_+task.pos.ms;
            if (next_pos >= wheel_ms_.size()) {
                next_pos -= wheel_ms_.size();
            }
            wheel_ms_[next_pos].push_back(task);
            task_map_[task.id] = &wheel_ms_[next_pos].back();
        }
    }
    tasks.clear();
}

//=========================================================
// 秒轮 tick
//=========================================================
void HAL::TimerWheel::TickSecondWheel() {
    cursor_sec_++;
    if (cursor_sec_ >= wheel_sec_.size()) {
        cursor_sec_ = 0;
        TickMinuteWheel();
    }
   // std::cout << "秒轮 tick " << cursor_sec_ << std::endl;

    auto& tasks = wheel_sec_[cursor_sec_];
    for (auto &task : tasks) {
        //AddTaskNoLock(task.interval_ms, task);
        if (task.repeat) { // 计算下一次执行位置
            auto next_pos = cursor_sec_+task.pos.sec;
            if (next_pos >= wheel_sec_.size()) {
                next_pos -= wheel_sec_.size();
            }
            //std::cout << "任务 " << task.id << " 重复添加到秒轮 " << next_pos << std::endl;
            wheel_sec_[next_pos].push_back(task);
            task_map_[task.id] = &wheel_sec_[next_pos].back();
        }
        
        // 偏移到毫秒轮轮转
        task.repeat = false;
        wheel_ms_[cursor_ms_+task.pos.ms].push_back(task);
    }
    tasks.clear();
}

//=========================================================
// 分钟轮 tick
//=========================================================
void HAL::TimerWheel::TickMinuteWheel() {
    cursor_min_++;
    if (cursor_min_ >= wheel_min_.size()) {
        cursor_min_ = 0;
    }
    //std::cout << "分钟轮 tick " << cursor_min_ << std::endl;

    auto& tasks = wheel_min_[cursor_min_];
    for (auto &task : tasks) {
        if (task.repeat) {
            // 计算下一次执行位置
            auto next_pos = cursor_min_+task.pos.min;
            if (next_pos >= wheel_min_.size()) {
                next_pos -= wheel_min_.size();
            }
            wheel_min_[next_pos].push_back(task);
            task_map_[task.id] = &wheel_min_[next_pos].back();
        }

        // 偏移到秒轮
        task.repeat = false;
        wheel_sec_[cursor_sec_+task.pos.sec].push_back(task);
        task_map_[task.id] = &wheel_sec_[cursor_sec_+task.pos.sec].back();
    }
    tasks.clear();
}

//=========================================================
// 位置计算（*）
//=========================================================
HAL::TimerPos HAL::TimerWheel::CalcPosition(int delay_ms) {
    HAL::TimerPos pos;

    auto real_tick = delay_ms / _interval_ms;
    
    pos.ms = (cursor_ms_ + real_tick) % wheel_ms_.size(); 
    pos.sec = (cursor_sec_ + (real_tick / wheel_ms_.size())) % wheel_sec_.size(); 
    pos.min = (cursor_min_ + (real_tick / (wheel_ms_.size() * wheel_sec_.size()))) % wheel_min_.size();

    std::cout << "任务延迟 " << delay_ms << "ms 计算位置: "
              << "ms=" << pos.ms*_interval_ms << ", sec=" << pos.sec << ", min=" << pos.min << std::endl;
    return pos;
}
